using System.Security.Claims;
using System.Text.Json;
using Eno.Domain.Entity.Log;
using Eno.Infrastructure.DataBase;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;

namespace Eno.Application.Services;

public class LogService : ILogService
{
    private readonly OriginDbContext _context;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public LogService(OriginDbContext context, IHttpContextAccessor httpContextAccessor)
    {
        _context = context;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task LogInfoAsync(string message, string? source = null, object? additionalData = null)
    {
        await CreateLogAsync("Info", message, null, source, additionalData);
    }

    public async Task LogWarningAsync(string message, string? source = null, object? additionalData = null)
    {
        await CreateLogAsync("Warning", message, null, source, additionalData);
    }

    public async Task LogErrorAsync(string message, Exception? exception = null, string? source = null, object? additionalData = null)
    {
        await CreateLogAsync("Error", message, exception, source, additionalData);
    }

    public async Task LogDebugAsync(string message, string? source = null, object? additionalData = null)
    {
        await CreateLogAsync("Debug", message, null, source, additionalData);
    }

    private async Task CreateLogAsync(string level, string message, Exception? exception = null, string? source = null, object? additionalData = null)
    {
        try
        {
            var httpContext = _httpContextAccessor.HttpContext;
            var log = new Log
            {
                Level = level,
                Message = message,
                Exception = exception?.ToString(),
                Source = source,
                CreatedAt = DateTime.UtcNow
            };

            if (httpContext != null)
            {
                log.UserId = httpContext.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                log.UserName = httpContext.User?.FindFirst(ClaimTypes.Name)?.Value;
                log.IpAddress = httpContext.Connection?.RemoteIpAddress?.ToString();
                log.RequestPath = httpContext.Request?.Path;
            }

            if (additionalData != null)
            {
                log.AdditionalData = JsonSerializer.Serialize(additionalData);
            }

            _context.Logs.Add(log);
            await _context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            // 避免日志记录本身出错导致应用崩溃
            Console.WriteLine($"Failed to log message: {ex.Message}");
        }
    }

    public async Task<List<Log>> GetLogsAsync(int pageNumber = 1, int pageSize = 50, string? level = null)
    {
        var query = _context.Logs.AsQueryable();

        if (!string.IsNullOrEmpty(level))
        {
            query = query.Where(l => l.Level == level);
        }

        return await query
            .OrderByDescending(l => l.CreatedAt)
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();
    }

    public async Task<Log?> GetLogByIdAsync(int id)
    {
        return await _context.Logs.FindAsync(id);
    }
}